package com.gc.server.service.impl;

import com.alibaba.excel.EasyExcel;
import com.gc.server.dao.ApplyDao;
import com.gc.server.dao.LevelDao;
import com.gc.server.dao.UserDao;
import com.gc.server.entity.*;
import com.gc.server.enums.BusApplyStatusEnum;
import com.gc.server.enums.LevelEnum;
import com.gc.server.service.DayOffService;
import com.gc.server.vo.ApplyUserVo;
import com.gc.server.vo.BusApplyVo;
import com.gc.server.vo.CostApplyVo;
import com.gc.server.vo.down.BusApplyDown;
import com.yf.response.RRException;
import com.yf.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.gc.server.dao.BusApplyDao;
import com.gc.server.service.BusApplyService;
import com.yf.service.impl.BaseServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

/**
 * 申请Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Wed Apr 08 09:33:59 CST 2020
 */
@Service
public class BusApplyServiceImpl extends BaseServiceImpl<BusApplyEntity> implements BusApplyService {

    private BusApplyDao busApplyDao;

    @Autowired
    private UserDao userDao;


    @Autowired
    public void setDao(BusApplyDao busApplyDao) {
        this.busApplyDao = busApplyDao;
        super.setBaseDao(busApplyDao);
    }


    @Override
    public List<BusApplyVo> queryListVo(BusApplyVo busApplyVo) {
        return busApplyDao.queryListVo(busApplyVo);
    }

    @Override
    public BusApplyVo getVo(Long id) {
        return busApplyDao.getVo(id);
    }


    /**内部方法**/


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplyEntity apply(Long userId, String info, List<BusApplyEntity> applyEntities) {
        ApplyEntity applyEntity = new ApplyEntity(new Date(),userId,info,BusApplyStatusEnum.WAIT.getIndex());
        applyDao.save(applyEntity);
        BigDecimal totalHour = BigDecimal.ZERO;
        for (int i = 0; i < applyEntities.size(); i++) {
            BusApplyEntity tem = applyEntities.get(i);
            BusApplyEntity busApplyEntity = new BusApplyEntity(userId,tem.getStartDate(),tem.getEndDate(),BusApplyStatusEnum.WAIT.getIndex(),1,new Date(),tem.getHours(),tem.getStartPlace(),tem.getEndPlace(),tem.getTripWay(),tem.getTripType(),info,applyEntity.getId());
            validate(busApplyEntity);
            save(busApplyEntity);
            totalHour = totalHour.add(busApplyEntity.getHours());
        }
        applyEntity.setHours(totalHour);
        applyDao.update(applyEntity);
        return applyEntity;
    }


    @Override
    public void downLoad(HttpServletResponse response, List<BusApplyVo> list) {
        try {
            List<BusApplyDown> datas = list.stream().map(item -> new BusApplyDown(item)).collect(Collectors.toList());
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), BusApplyDown.class).sheet("模板").doWrite(datas);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Autowired
    private ApplyDao applyDao;

    /**
     * 外部方法实现
     **/

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public BusApplyEntity apply(Long userId, String info, Date startDate, Date endDate, Integer type, Integer leaveType, BigDecimal hours, String startPlace,String midPlace, String endPlace, String tripWay, String tripType) {
//        if (startDate.after(endDate)) {
//            throw new RRException("时间有误!");
//        }
//        if (hours.compareTo(BigDecimal.ZERO) < 0) {
//            throw new RRException("请假时间过短!");
//        }
//        BusApplyEntity busApplyEntity = new BusApplyEntity(userId, startDate, endDate, BusApplyStatusEnum.WAIT.getIndex(), type, new Date(), info, hours);
//        busApplyEntity.setLeaveType(leaveType);
//        busApplyEntity.setStartPlace(startPlace);
//        busApplyEntity.setMidPlace(midPlace);
//        busApplyEntity.setEndPlace(endPlace);
//        busApplyEntity.setTripType(tripType);
//        busApplyEntity.setTripWay(tripWay);
//        //计算时间
//        save(busApplyEntity);
//        return busApplyEntity;
//    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public BusApplyEntity applyLeave(Long userId, String info, Date startDate, Date endDate, Integer type, Integer leaveType, BigDecimal hours) {
        BusApplyEntity busApplyEntity = new BusApplyEntity(userId,startDate,endDate,BusApplyStatusEnum.WAIT.getIndex(),type,new Date(),info,hours,leaveType);
        validate(busApplyEntity);
        save(busApplyEntity);
        return busApplyEntity;
    }

  void   validate(BusApplyEntity applyEntity){
        if (applyEntity.getStartDate().after(applyEntity.getEndDate())) {
            throw new RRException("时间有误!");
        }
        if (applyEntity.getHours().compareTo(BigDecimal.ZERO) < 0) {
            throw new RRException("请假时间过短!");
        }
    }

    @Autowired
    private DayOffService dayOffService;

    @Override
    public Integer sumCheck(Long userId,Integer type) {
        return busApplyDao.sumCheck(userId,BusApplyStatusEnum.WAIT.getIndex(),type);
    }

    @Override
    public List<BusApplyEntity> findByAid(Long id) {
        return busApplyDao.findByAid(id);
    }

    // 计算时间
    public BigDecimal calHours(Date start, Date end) {
        if (start.after(end)) {
            return BigDecimal.ZERO;
        }
        Long startDayTime = 0L;
        Long endDayTime = 0L;
        //  首先开始和结束的时间
        startDayTime = getTime(start);
        endDayTime = getTime(end);
        //  计算总共请假的时间
        Long day = DateUtil.getDays(start, end);//相差的天数
        Long totalTime = day * getDayTime() - startDayTime + endDayTime;
        // 去掉请假的时间

        List<DayOffEntity> dayOffEntities = dayOffService.findByDate(start, end);

        //如果有请假
        Integer offDay = dayOffEntities.size();
        if (offDay > 0) {
            //如果请假开始在节假日
            if (DateUtil.isSameDay(start, dayOffEntities.get(0).getDay())) {
                offDay--; //减一天假期
                //去除请假当天的时间
                totalTime -= (getDayTime() - startDayTime);
            }

            //  如果请假结束是否在放假时间
            if (DateUtil.isSameDay(end, dayOffEntities.get(dayOffEntities.size() - 1).getDay())) {
                if (!DateUtil.isSameDay(start, end)) {//结束也在假期 且跟开始不是一天
                    offDay--;
                }
                totalTime -= endDayTime;
            }
            // 减去剩余的假期
            totalTime -= offDay * getDayTime();
        }
        return new BigDecimal(totalTime).divide(new BigDecimal(60 * 60 * 1000), 1, BigDecimal.ROUND_HALF_UP);
    }


    //时间转日期
    Date timeToDateTime(Date date, String time) {
        //上班时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd " + time);
        Date res = new Date(dateFormat.format(date));
        return res;
    }

    public static void main(String[] args) {
      Long a = 1L;
      int b = 1;
        System.out.print(a == b);
        System.out.print(a.equals(b));
    }

    private String startWorkTime = "08:00:00";
    private String startMidWorkTime = "12:00:00";
    private String endMidWorkTime = "13:00:00";
    private String endWorkTime = "18:00:00";

    //一整天时间
    Long getDayTime() {
        Date start = new Date();
        return getMorTime() + getNoonTime();
    }

    //上午时间
    Long getMorTime() {
        return timeToDateTime(new Date(), startMidWorkTime).getTime() - timeToDateTime(new Date(), startWorkTime).getTime();
    }

    //下午时间
    Long getNoonTime() {
        return timeToDateTime(new Date(), endWorkTime).getTime() - timeToDateTime(new Date(), endMidWorkTime).getTime();
    }


    // 获取请假时间
    Long getTime(Date start) {
        //上班前
        if (start.getTime() < timeToDateTime(start, startWorkTime).getTime()) {
            return 0L;
        } else if (start.getTime() < timeToDateTime(start, startMidWorkTime).getTime()) { //午休前
            return start.getTime() - timeToDateTime(start, startWorkTime).getTime();
        } else if (start.getTime() < timeToDateTime(start, endMidWorkTime).getTime()) {//结束午休前
            return getMorTime();
        } else if (start.getTime() < timeToDateTime(start, endWorkTime).getTime()) {//下班前
            return getMorTime() + start.getTime() - timeToDateTime(start, endMidWorkTime).getTime();
        } else { //下班后
            return getDayTime();
        }
    }

    @Autowired
    private LevelDao levelDao;


    @Override
    public BusApplyEntity check(Long userId, Long id, Integer status, String remark) {
        BusApplyEntity busApplyEntity = busApplyDao.get(id);
        if (!busApplyEntity.getStatus().equals(BusApplyStatusEnum.WAIT.getIndex())) {
            throw new RRException("请勿重复操作!");
        }
        busApplyEntity.setAdminId(userId);
        UserEntity userEntity = userDao.get(userId);
        busApplyEntity.setAdminName(userEntity.getName());
        busApplyEntity.setRemark(remark);
        //如果通过的话 一天及以上由上一级审批  1-3天需要两级 3天以上总监
        if (status.equals(BusApplyStatusEnum.PASS.getIndex())) {
            LevelEntity adminLevel = levelDao.findByUserId(userId);
            BigDecimal ondDay = new BigDecimal(9);
            BigDecimal threeDay = new BigDecimal(27);
            if(adminLevel.getId() == LevelEnum.MANAGER3.getIndex()||adminLevel.getId() == LevelEnum.MANAGER2.getIndex()||busApplyEntity.getHours().compareTo(ondDay)<=0){ // 只有一天的 总监直接通过
                busApplyEntity.setStatus(BusApplyStatusEnum.PASS.getIndex());
            }else { // 不是总监  且超过一天的
                if(busApplyEntity.getHours().compareTo(threeDay)<=0){
                    // 1-3天 必须两级
                    LevelEntity userLevel = levelDao.findByUserId(busApplyEntity.getUserId());
                    if(adminLevel.getLv() - userLevel.getLv()==2){ //必须有两级 通过
                        busApplyEntity.setStatus(BusApplyStatusEnum.PASS.getIndex());
                    }
                }
            }
        } else {
            busApplyEntity.setStatus(status);
        }
        update(busApplyEntity);
        return busApplyEntity;
    }

    @Override
    public List<ApplyUserVo> findMyShopUser(Long userId) {
        return busApplyDao.findMyShopUser(userId);
    }

    @Override
    public List<ApplyUserVo> findByUser(Long userId) {
        return busApplyDao.findByUser(userId);
    }

    @Override
    public List<ApplyUserVo> findMyShopUserAndDate(Long topUserId, Long userId, Date startDate, Date endDate) {
        return busApplyDao.findMyShopUserAndDate(topUserId, userId, startDate, endDate);
    }

    @Override
    public List<ApplyUserVo> findByUserAndDate(Long userId, Date startDate, Date endDate) {
        return busApplyDao.findByUserAndDate(userId, startDate, endDate);
    }

}
